# android webview 开发
开发工具:
Android Studio Arctic Fox | 2020.3.1 Patch 2
vscode 1.60.0
Chrome: 91.0.4472.164
Node.js: 14.16.0
# 1、创建项目
File => New => New Project => Empty Activity
(1)第一步选择 New Project
(2)第二步选择 Empty Activity
(3)第三步设置项目名称及地址
# 2、目录结构
(1)设置目录结构
设置项目结构为 Project,该目录下文件路径非常清晰
(2)目录结构说明
使用指引创建空项目,会自动生成标准的项目目录结构
.gradle
Android Studio 构建系统.idea
编辑器 配置app
应用目录build
打包后的目录文件libs
第三方 jar 包src
源文件main
源文件主目录java
代码目录com.xxx.myapplication2
源代码文件目录
res
resource 资源layout
页面布局目录
AndroidManifest.xml
应用清单
.gitignore
git 不需要提交的文件列表build.gradle
配置整个 app 应用proguard-rules.pro
编译混淆配置
gradle/wrapper
简化 Gradle 本身的安装、部署.gitignore
git 不需要提交的文件列表build.gradle
配置整个工程gradle.properties
Gradle 文件的全局性的配置gradlew
UN*X 的 Gradle 启动脚本gradlew.bat
Windows 的 Gradle 启动脚本local.properties
SDK的位置配置settings.gradle
配置 gradle
# 3、设置 Android SDK 版本
android {
compileSdk 31
buildToolsVersion '31.0.0'
compileSdkVersion 31
defaultConfig {
applicationId "com.example.myapplication2"
minSdk 21 // 最小sdk
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 4、设置 WebView layout
layout 目录地址:
app => src => main => res => layout => activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:aandroid="http://schemas.android.com/apk/res/android"
aandroid:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context=".MainActivity">
<WebView
android:id="@+id/wv_webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="horizontal"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
配置 WebView 组件 id android:id="@+id/wv_webview"
# 5、配置程序权限
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
<uses-feature android:name="android.hardware.camera" android:required="true"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 6、在程序入口初始化 WebView
一般程序入口文件为:
app => src => main => java => com.xxx.myapplication2 => MainActivity.java
在 onCreate()
里面编写初始化程序:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 开启 WebView 长截图,在 setContentView() 方法前面设置才有效
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
WebView.enableSlowWholeDocumentDraw();
}
setContentView(R.layout.activity_main);
// 隐藏顶部标题栏
getSupportActionBar().hide();
// 去除状态栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 初始化 WebView
initWebView();
}
// 销毁 webView
@Override
protected void onDestroy() {
if (this.webView != null) {
webView.destroy();
}
super.onDestroy();
}
@Override
protected void onResume() {
/**
* 设置为横屏
*/
// if(getRequestedOrientation()!= ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE){
// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// }
super.onResume();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
初始化代码:
private WebView webView;
private void init()
{
webView = (WebView) findViewById(R.id.wv_webview);
WebSettings settings = webView.getSettings(); // webView 配置项
settings.setUseWideViewPort(true); // 是否启用对视口元标记的支持
settings.setJavaScriptEnabled(true); // 是否启用 JavaScript
settings.setDomStorageEnabled(true); // 是否启用本地存储(允许使用 localStorage 等)
settings.setAllowFileAccess(true); // 是否启用文件访问
settings.setAppCacheEnabled(true); // 是否应启用应用程序缓存
settings.setAppCacheMaxSize(1024*1024*8); // 设置应用程序缓存内容的最大大小
String appCachePath = getApplicationContext().getCacheDir().getAbsolutePath(); // 缓存地址
settings.setAppCachePath(appCachePath); // 设置缓存地址
settings.setAllowContentAccess(true); // 是否启用内容 URL 访问
settings.setJavaScriptCanOpenWindowsAutomatically(true); // 是否允许 JS 弹窗
settings.setMediaPlaybackRequiresUserGesture(false); // 是否需要用户手势来播放媒体
settings.setLoadWithOverviewMode(true); // 是否以概览模式加载页面,即按宽度缩小内容以适应屏幕
settings.setBuiltInZoomControls(true); // 是否应使用其内置的缩放机制
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
// Hide the zoom controls for HONEYCOMB+
settings.setDisplayZoomControls(false); // 是否应显示屏幕缩放控件
}
// Enable remote debugging via chrome://inspect
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true); // 是否开启 WebView 调试功能,配合PC端 Chrome DevTools 功能使用
}
settings.setAllowFileAccessFromFileURLs(true); // 是否应允许在文件方案 URL 上下文中运行的 JavaScript 访问来自其他文件方案 URL 的内容
settings.setAllowUniversalAccessFromFileURLs(true); // 是否应允许在文件方案URL上下文中运行的 JavaScript 访问任何来源的内容
webView.loadUrl("https://www.baidu.com"); // 设置访问地址
webView.addJavascriptInterface(new JsInterface(this, webView, MainActivity.this),"jsWebView"); // 设置 js 调用接口
webView.setDrawingCacheEnabled(true); // 启用或禁用图形缓存
webView.setWebViewClient(new WVViewClient()); // 帮助 WebView 处理各种通知、请求事件
webView.setWebChromeClient(new WVChromeClient(this, MainActivity.this)); // 处理解析,渲染网页
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
new JsInterface()
代码:
public class JsInterface {
private Context _context;
private final WebView _webview;
private MainActivity _m;
public JsInterface(Context context, WebView webView, MainActivity mainActivity)
{
_context = context;
_webview = webView;
_m = mainActivity;
}
// 开放 test 方法给 js,在 web 页面使用 window.test('hello'); 调用。
@JavascriptInterface
public void test(String val){
Log.i("test",val);
_webview.post(new Runnable() {
@Override
public void run() {
_webview.loadUrl("javascript:cbMessage('message');",null); // java 调用 js 的 cbMessage 方法
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
new WVViewClient()
代码:
public class WVViewClient extends WebViewClient {
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
if (handler != null) {
handler.proceed();//忽略证书的错误继续加载页面内容,不会变成空白页面
}
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
new WVChromeClient()
代码:
public class WVChromeClient extends WebChromeClient{
private Context _context;
private MainActivity _m;
public WVChromeClient(Context context, MainActivity mainActivity)
{
_context = context;
_m = mainActivity;
}
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
Log.d("MainActivity","newProgress:"+ newProgress );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15